﻿using EventBus;
using LiteStep.Currencies;
using LiteStep.Events;
using LiteStep.Exchanges;
using LiteStep.Exchanges.Vircurex;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LiteStep.Utils.Recorders.Vircurex
{
    public class VircurexDepthRecorder<TFrom, TTo> : IDepthRecorder<Depth<TFrom, TTo>>
        where TFrom : ICurrency
        where TTo : ICurrency
    {
        protected IEventBus eventBus { get; set; }
		private IHandlerRegistration registration { get; set; }

        public VircurexDepthRecorder(IEventBus eventBus)
		{
			this.eventBus = eventBus;
		}

		public void Register()
		{
			if (registration == null)
			{
				registration = eventBus.AddHandler(AfterDepthResponseEvent<Depth<TFrom, TTo>>.TYPE, this);
			}
		}

		public void Unregister()
		{
			if (registration != null)
			{
				registration.RemoveHandler();
				registration = null;
			}
		}

		public void OnAfterDepthResponseEvent(AfterDepthResponseEvent<Depth<TFrom, TTo>> e)
		{
			if (e == null || e.Depth == null)
			{
				LiteStep.Log.ErrorFormat("The Vircurex {0}/{1} depth was not received", typeof(TFrom).Name.ToUpper(), typeof(TTo).Name.ToUpper());
				return; 
			}

			try
			{
				using (var liteStepContext = LiteStep.Ninjector.Get<LiteStepContext>())
				{
					var depth = new VircurexDepth();
					depth.Base = (int)Enum.Parse(typeof(Currencies.Currencies), typeof(TFrom).Name);
					depth.Alt = (int)Enum.Parse(typeof(Currencies.Currencies), typeof(TTo).Name);
					depth.Version = 1;
					depth.InsertedOn = DateTime.Now;

                    liteStepContext.VircurexDepths.Add(depth);
                    liteStepContext.SaveChanges();

                    foreach (var ask in e.Depth.Asks ?? new List<IList<double>>())
                    {
                        var depthValue = new VircurexDepthValue();
                        depthValue.Depth = depth.Id;
                        depthValue.Type = (int)OrderTypes.Ask;
                        depthValue.Price = (decimal)ask[Depth<TFrom, TTo>.PriceIndex];
                        depthValue.Volume = (decimal)ask[Depth<TFrom, TTo>.VolumeIndex];

                        liteStepContext.VircurexDepthValues.Add(depthValue);
                    }

                    foreach (var bid in e.Depth.Bids ?? new List<IList<double>>())
                    {
                        var depthValue = new VircurexDepthValue();
                        depthValue.Depth = depth.Id;
                        depthValue.Type = (int)OrderTypes.Bid;
                        depthValue.Price = (decimal)bid[Depth<TFrom, TTo>.PriceIndex];
                        depthValue.Volume = (decimal)bid[Depth<TFrom, TTo>.VolumeIndex];

                        liteStepContext.VircurexDepthValues.Add(depthValue);
                    }

					liteStepContext.SaveChanges();
				}
			}
			catch (Exception ex)
			{
				  LiteStep.Log.Error(String.Format("There was an error saving the Vircurex {0}/{1} depth", typeof(TFrom).Name.ToUpper(), typeof(TTo).Name.ToUpper()), ex);
			}
			
		}
    }
}
